﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;

namespace FluentValidationExample.Validations;

public class TestObjectModelValidator : ObjectModelValidator
{
    /// <summary>
    /// 禁用内置模型验证
    /// </summary>
    private readonly bool disableBuiltInModelValidation;

    public TestObjectModelValidator(IModelMetadataProvider modelMetadataProvider, IList<IModelValidatorProvider> validatorProviders,
        bool disableBuiltInModelValidation)
        : base(modelMetadataProvider, validatorProviders)
    {
        this.disableBuiltInModelValidation = disableBuiltInModelValidation;
    }

    public override ValidationVisitor GetValidationVisitor(ActionContext actionContext, IModelValidatorProvider validatorProvider,
        ValidatorCache validatorCache,
        IModelMetadataProvider metadataProvider, ValidationStateDictionary? validationState)
    {
        return new TestValidationVisitor(actionContext, validatorProvider, validatorCache, metadataProvider, validationState,
            disableBuiltInModelValidation);
    }
}

public class TestValidationVisitor : ValidationVisitor
{
    /// <summary>
    /// 禁用内置模型验证
    /// </summary>
    private readonly bool disableBuiltInModelValidation;

    public TestValidationVisitor(ActionContext actionContext,
        IModelValidatorProvider validatorProvider,
        ValidatorCache validatorCache,
        IModelMetadataProvider metadataProvider,
        ValidationStateDictionary? validationState,
        bool disableBuiltInModelValidation)
        : base(actionContext, validatorProvider, validatorCache, metadataProvider, validationState)
    {
        this.disableBuiltInModelValidation = disableBuiltInModelValidation;
    }

    public override bool Validate(ModelMetadata? metadata, string? key, object? model, bool alwaysValidateAtTopLevel)
    {
        // If built in model validation is disabled return true for later validation in the action filter.
        return disableBuiltInModelValidation || base.Validate(metadata, key, model, alwaysValidateAtTopLevel);
    }

#if !NETCOREAPP3_1
    public override bool Validate(ModelMetadata? metadata, string? key, object? model, bool alwaysValidateAtTopLevel, object? container)
    {
        // If built in model validation is disabled return true for later validation in the action filter.
        return disableBuiltInModelValidation || base.Validate(metadata, key, model, alwaysValidateAtTopLevel, container);
    }
#endif
}